#include "OgreRefAppSupportSpotCalculator.h"
#include "OgreRefAppSoccerPitch.h"
#include "OgreRefAppRegion.h"
#include "OgreRefAppSoccerTeam.h"
#include "OgreRefAppPlayerBase.h"

namespace OgreRefApp
{

//------------------------------- dtor ----------------------------------------
//-----------------------------------------------------------------------------
    SupportSpotCalculator::~SupportSpotCalculator()
    {
        delete m_pRegulator;
    }


//------------------------------- ctor ----------------------------------------
//-----------------------------------------------------------------------------
    SupportSpotCalculator::SupportSpotCalculator(int           numX,
            int           numY,
            SoccerTeam*   team):m_pBestSupportingSpot(NULL),
            m_pTeam(team)
    {
        Region* PlayingField = team->Pitch()->playingArea();

        //calculate the positions of each sweet spot, create them and
        //store them in m_Spots
        Real HeightOfSSRegion = PlayingField->Height() * 0.8;
        Real WidthOfSSRegion  = PlayingField->Width() * 0.9;
        Real SliceX = WidthOfSSRegion /  numX ;
        Real SliceY = HeightOfSSRegion / numY;

        Real left  = PlayingField->Left() + (PlayingField->Width()-WidthOfSSRegion)/2.0 + SliceX/2.0;
        Real right = PlayingField->Right() - (PlayingField->Width()-WidthOfSSRegion)/2.0 - SliceX/2.0;
        Real top   = PlayingField->Top() + (PlayingField->Height()-HeightOfSSRegion)/2.0 + SliceY/2.0;

        for (int x=0; x<(numX/2)-1; ++x)
        {
            for (int y=0; y<numY; ++y)
            {
                if (m_pTeam->Color() == SoccerTeam::blue)
                {
                    m_Spots.push_back(SupportSpot(Ogre::Vector3(left+x*SliceX, top+y*SliceY, BallRadius), 0.0));
                }

                else
                {
                    m_Spots.push_back(SupportSpot(Ogre::Vector3(right-x*SliceX, top+y*SliceY, BallRadius), 0.0 ));
                }
            }
        }

        //create the regulator
        //m_pRegulator = new Regulator(SupportSpotUpdateFreq);
    }


//--------------------------- DetermineBestSupportingPosition -----------------
//
//  see header or book for description
//-----------------------------------------------------------------------------
    Ogre::Vector3 SupportSpotCalculator::DetermineBestSupportingPosition()
    {

        //only update the spots every few frames
        if (m_pBestSupportingSpot)
        {
            return m_pBestSupportingSpot->m_vPos;
        }

        //reset the best supporting spot
        m_pBestSupportingSpot = NULL;

        Real BestScoreSoFar = 0.0;

        std::vector<SupportSpot>::iterator curSpot;

        for (curSpot = m_Spots.begin(); curSpot != m_Spots.end(); ++curSpot)
        {

            //first remove any previous score. (the score is set to one so that
            //the viewer can see the positions of all the spots if he has the
            //aids turned on)
            curSpot->m_dScore = 1.0;

            //Test 1. is it possible to make a safe pass from the ball's position
            //to this position?


            if (m_pTeam->isPassSafeFromAllOpponents(m_pTeam->ControllingPlayer()->getPosition(),
                                                    curSpot->m_vPos,
                                                    m_pTeam->SupportingPlayer(),
                                                    MaxPassingForce))
            {

                curSpot->m_dScore += Spot_CanPassScore;
            }





            //Test 2. Determine if a goal can be scored from this position.
            if ( m_pTeam->CanShoot(curSpot->m_vPos,
                                   MaxShootingForce))
            {
                curSpot->m_dScore += Spot_CanScoreFromPositionScore;
            }

            //Test 3. calculate how far this spot is away from the controlling
            //player. The further away, the higher the score. Any distances further
            //away than OptimalDistance pixels do not receive a score.
            if (m_pTeam->SupportingPlayer())
            {
                const double OptimalDistance = 200.0;

                double dist = m_pTeam->ControllingPlayer()->getPosition().distance(curSpot->m_vPos);

                double temp = fabs(OptimalDistance - dist);

                if (temp < OptimalDistance)
                {

                    //normalize the distance and add it to the score
                    curSpot->m_dScore += Spot_DistFromControllingPlayerScore *
                                         (OptimalDistance-temp)/OptimalDistance;
                }
            }


            //check to see if this spot has the highest score so far
            if (curSpot->m_dScore > BestScoreSoFar)
            {
                BestScoreSoFar = curSpot->m_dScore;

                m_pBestSupportingSpot = &(*curSpot);
            }

        }

        return m_pBestSupportingSpot->m_vPos;
    }





//------------------------------- GetBestSupportingSpot -----------------------
//-----------------------------------------------------------------------------
    Ogre::Vector3 SupportSpotCalculator::GetBestSupportingSpot()
    {
        if (m_pBestSupportingSpot)
        {
            return m_pBestSupportingSpot->m_vPos;
        }

        else
        {

            return DetermineBestSupportingPosition();
        }
    }



}
